package master

import (
	"context"
	"crontab/common"
	"encoding/json"
	"go.etcd.io/etcd/api/v3/mvccpb"
	clientv3 "go.etcd.io/etcd/client/v3"
	"time"
)

// 单例

type EtcdJob struct {
	EtcdClient *clientv3.Client
	EtcdKv clientv3.KV
	EtcdLease clientv3.Lease
}

// 写入杀死命令信号
func (etcd *EtcdJob) EtcdKillJob(jobName string) (err error) {

	var (
		key string
		leaseGranResp *clientv3.LeaseGrantResponse
	)
	key = common.ETCD_KILL_KEY_PREFIX + jobName

	// 给key设置过期时间
	// 创建一个租约
	leaseGranResp,err = etcd.EtcdLease.Grant(context.TODO(),3)
	if err != nil {
		return
	}
	// put操作
	_,err = etcd.EtcdKv.Put(context.TODO(),key,"",clientv3.WithLease(leaseGranResp.ID))
	if err != nil {
		return
	}
	return
}

// 获取job列表
func (etcd *EtcdJob) EtcdJobList() (jobList []*common.Job,err error){
	var (
		key string
		getResp *clientv3.GetResponse
		itemValue *mvccpb.KeyValue
		jobItem *common.Job
	)

	// 初始化jobList数组
	jobList = make([]*common.Job,0)

	key = common.ETCD_KEY_PREFIX
	getResp,err = etcd.EtcdKv.Get(context.TODO(),key,clientv3.WithPrefix())
	if err != nil {
		return
	}
	for _, itemValue = range getResp.Kvs {
		jobItem = &common.Job{}
		if err = json.Unmarshal(itemValue.Value,jobItem);err != nil {
			err = nil
			continue
		}
		jobList = append(jobList,jobItem)
	}
	return
}

// 删除job任务
func (etcd *EtcdJob) DelEtcdJob(jobName string) (prevKv *common.Job,err error) {
	var (
		key string
		delResp *clientv3.DeleteResponse
	)
	key = common.ETCD_KEY_PREFIX + jobName
	delResp,err = etcd.EtcdKv.Delete(context.TODO(),key,clientv3.WithPrevKV())
	if err != nil {
		return
	}

	if len(delResp.PrevKvs) == 0 {
		return
	}

	prevKv = &common.Job{}
	err = json.Unmarshal(delResp.PrevKvs[0].Value,prevKv)
	if err != nil {
		return
	}
	return
}


// 保存job
func (etcd *EtcdJob) SaveJob(job *common.Job) (prevJob *common.Job,err error) {
	var (
		jobByte []byte
		key string
		putResp *clientv3.PutResponse
	)
	jobByte,_ = json.Marshal(job)

	key = common.ETCD_KEY_PREFIX + job.JobName
	// 写入etcd
	putResp,err = etcd.EtcdKv.Put(context.TODO(),key,string(jobByte),clientv3.WithPrevKV())

	if putResp.PrevKv != nil {
		prevJob = &common.Job{}
		err = json.Unmarshal(putResp.PrevKv.Value,prevJob)
		return
	}
	return

}

var  (
	G_EtcdJob *EtcdJob
)

func InitEtcd() (err error) {
	var (
		config *clientv3.Config
		etcdClient *clientv3.Client
		kv clientv3.KV
		lease clientv3.Lease
	)
	config = &clientv3.Config{
		Endpoints: G_Config.ApiEndpoints,
		DialTimeout: time.Second * time.Duration(G_Config.ApiEtcdTimeout),
		Username: G_Config.EtcdUserName,
		Password: G_Config.EtcdPassword,
	}
	etcdClient,err = clientv3.New(*config)
	if err != nil {
		return err
	}

	kv = clientv3.NewKV(etcdClient)

	lease = clientv3.NewLease(etcdClient)


	G_EtcdJob = &EtcdJob{
		EtcdClient: etcdClient,
		EtcdKv: kv,
		EtcdLease: lease,
	}

	return nil
}



